package com.basics.framework.web.exception;


import com.basics.common.exception.BaseException;
import com.basics.common.exception.CustomException;
import com.basics.common.exception.DemoModeException;
import com.basics.common.utils.StringUtils;
import com.basics.framework.web.domain.RestResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.naming.AuthenticationException;

@RestControllerAdvice
public class GlobalExceptionHandler {
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    public GlobalExceptionHandler() {
    }

    @ExceptionHandler({BaseException.class})
    public RestResult<String> baseException(BaseException e) {
        return RestResult.error(e.getMessage());
    }

    @ExceptionHandler({CustomException.class})
    public RestResult<String> businessException(CustomException e) {
        return StringUtils.isNull(e.getCode()) ? RestResult.error(e.getMessage()) : RestResult.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler({NoHandlerFoundException.class})
    public RestResult<String> handlerNoFoundException(Exception e) {
        log.error(e.getMessage(), e);
        return RestResult.error(404, "路径不存在，请检查路径是否正确");
    }

    @ExceptionHandler({AccessDeniedException.class})
    public RestResult<String> handleAuthorizationException(AccessDeniedException e) {
        log.error(e.getMessage());
        return RestResult.error(403, "没有权限，请联系管理员授权");
    }

    @ExceptionHandler({AuthenticationException.class})
    public RestResult<String> handleAuthorizationException(AuthenticationException e) {
        log.error(e.getMessage());
        return RestResult.error(408, "token失效或者过期，请联系管理员授权");
    }

    @ExceptionHandler({SecurityException.class})
    public RestResult<String> businessException(SecurityException e) {
        return RestResult.error(e.getMessage());
    }

    @ExceptionHandler({AccountExpiredException.class})
    public RestResult<String> handleAccountExpiredException(AccountExpiredException e) {
        log.error(e.getMessage(), e);
        return RestResult.error(e.getMessage());
    }

    @ExceptionHandler({UsernameNotFoundException.class})
    public RestResult<String> handleUsernameNotFoundException(UsernameNotFoundException e) {
        log.error(e.getMessage(), e);
        return RestResult.error(e.getMessage());
    }

    @ExceptionHandler({Exception.class})
    public RestResult<String> handleException(Exception e) {
        log.error(e.getMessage(), e);
        return RestResult.error("系统异常，请联系管理员");
    }

    @ExceptionHandler({BindException.class})
    public RestResult<String> validatedBindException(BindException e) {
        log.error(e.getMessage(), e);
        String message = ((ObjectError)e.getAllErrors().get(0)).getDefaultMessage();
        return RestResult.error(message);
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Object validExceptionHandler(MethodArgumentNotValidException e) {
        log.error(e.getMessage(), e);
        String message = e.getBindingResult().getFieldError().getDefaultMessage();
        return RestResult.error(message);
    }

    @ExceptionHandler({DemoModeException.class})
    public RestResult<String> demoModeException(DemoModeException e) {
        return RestResult.error("演示模式，不允许操作");
    }
}
